package org.infodavid.common.messaging;

import java.io.Serializable;
import java.lang.reflect.Field;
import java.util.List;

import junit.framework.Assert;
import junit.framework.TestCase;
import net.sf.ehcache.Cache;

import org.junit.After;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;

import org.infodavid.common.messaging.MessagingService.IConnection;

/**
 * The Class MessagingServiceTestManual.
 */
@SuppressWarnings("rawtypes")
public class MessagingServiceTestManual extends TestCase {

  /**
   * Sets the up before class.
   * @throws java.lang.Exception *
   * @throws Exception the exception
   */
  @BeforeClass
  public static void setUpBeforeClass() throws Exception {}

  /** Queue name. */
  private static final String QUEUE_NAME1 = "queue/MessagingTest1";

  /** Remote queues. */
  private static final String HOST_OF_REMOTE_QUEUES = "127.0.0.1";

  /**
   * Sets the up.
   * @throws java.lang.Exception *
   * @throws Exception the exception
   */
  @Override
  @Before
  public void setUp() throws Exception {}

  /**
   * Tear down.
   * @throws java.lang.Exception *
   * @throws Exception the exception
   */
  @Override
  @After
  public void tearDown() throws Exception {}

  /**
   * Test method for {@link org.infodavid.common.messaging.MessagingService#getInstance()}.
   */
  @Test
  public final void testGetSingleton() {
    // Get instance 1
    final MessagingService srv1 = MessagingService.getInstance();
    final MessagingService srv2 = MessagingService.getInstance();

    assertNotNull("Singleton is null", srv1);
    assertNotNull("Singleton is null", srv2);
    assertEquals("Instance 1 != Instance 2", srv1, srv2);
  }

  /**
   * Test method for {@link org.infodavid.common.messaging.MessagingService#closeConnections()} .
   * @throws Exception the exception
   */
  @Test
  public final void testCloseConnections() throws Exception {
    final Field field = MessagingService.getInstance().getClass().getDeclaredField("cache");

    MessagingService.getInstance().closeConnections();

    field.setAccessible(true);
    final Cache cache = (Cache)field.get(MessagingService.getInstance());

    assertEquals("Wrong number of elements in cache", 0, cache.getSize());
  }

  /**
   * Test method for
   * {@link org.infodavid.common.messaging.MessagingService#sendObjectMessages(java.lang.String, java.lang.String, java.io.Serializable[])}
   * .
   * @throws Exception the exception
   */

  @Test
  public final void testSendObjectMessagesStringStringSerializableArray() throws Exception {
    final Serializable[] messages = new Serializable[] {
        Long.valueOf(System.currentTimeMillis()), Long.valueOf(System.currentTimeMillis() + 1000)
    };
    final DefaultListener listener = new DefaultListener();
    final IConnection connection =
        MessagingService.getInstance().listen(HOST_OF_REMOTE_QUEUES, QUEUE_NAME1, listener);
    Throwable error = null;

    assertNotNull("Connection is null", connection);

    connection.connect();

    try {
      MessagingService.getInstance().sendObjectMessages(HOST_OF_REMOTE_QUEUES, QUEUE_NAME1,
          messages);
    }
    catch (final Exception e) {
      error = e;
      e.printStackTrace();
    }

    Assert.assertNull("An error occurs while sending message", error);

    System.out.println("Waiting for messages ...");

    try {
      Thread.sleep(1000);
    }
    catch (final java.lang.InterruptedException ie) {
      ie.printStackTrace(System.err);
    }

    connection.disconnect();

    final List recieved = listener.getReceivedMessageList();

    assertTrue("Messages not recieved", messages.length <= recieved.size());

    for (final Object msg : messages) {
      System.out.println("Recieved: " + msg);

      assertTrue("Wrong messages recieved", recieved.contains(msg));
    }
  }

  /**
   * Test method for
   * {@link org.infodavid.common.messaging.MessagingService#sendTextMessages(java.lang.String, java.lang.String, java.lang.String[])}
   * .
   * @throws Exception the exception
   */
  @Test
  public final void testSendTextMessagesStringStringStringArray() throws Exception {
    final String[] messages = new String[] {
        "TEST_MESSAGE_" + System.currentTimeMillis(), "TEST_MESSAGE_" + System.currentTimeMillis()
    };
    final DefaultListener listener = new DefaultListener();
    final IConnection connection =
        MessagingService.getInstance().listen(HOST_OF_REMOTE_QUEUES, QUEUE_NAME1, listener);
    Throwable error = null;

    assertNotNull("Connection is null", connection);

    connection.connect();

    try {
      MessagingService.getInstance().sendTextMessages(HOST_OF_REMOTE_QUEUES, QUEUE_NAME1, messages);
    }
    catch (final Exception e) {
      error = e;
      e.printStackTrace();
    }

    Assert.assertNull("An error occurs while sending message", error);

    System.out.println("Waiting for messages ...");

    try {
      Thread.sleep(1000);
    }
    catch (final java.lang.InterruptedException ie) {
      ie.printStackTrace(System.err);
    }

    connection.disconnect();

    final List recieved = listener.getReceivedMessageList();

    assertTrue("Messages not recieved", messages.length <= recieved.size());

    for (final Object msg : messages) {
      System.out.println("Recieved: " + msg);

      assertTrue("Wrong messages recieved", recieved.contains(msg));
    }
  }
}
